package msghandler

import (
	"fmt"
	"reflect"
	"strings"
	"sync"

	"gitee.com/night-tc/gobige/common"
	"gitee.com/night-tc/gobige/global"
	"gitee.com/night-tc/gobige/logger"
	"gitee.com/night-tc/gobige/msgdef"
	"gitee.com/night-tc/gobige/safecontainer"
	"github.com/spf13/viper"
)

/*
	MsgHandler 作为底层通讯层与上层应用层之间逻辑传递的桥梁
*/

type IMsgHandler interface {
	//处理消息
	DoMsg()
	//处理Msg消息
	DoNormalMsg(name string, content msgdef.IMsg) error
	//处理RPC消息
	DoRPCMsg(methodName string, content msgdef.IMsg) error
	// 处理Srv消息
	DoSrvMsg(name string, req, msg msgdef.IMsg)
	// FireMsg 触发消息, 保证不被挂起
	FireMsg(name string, content msgdef.IMsg)
	// FireRPC 触发消息, 保证不被挂起
	FireRPC(method string, content msgdef.IMsg)
	// FireSrv 触发消息, 保证不被挂起
	FireSrv(name string, req, msg msgdef.IMsg)

	// RegMsgProc 注册消息处理对象
	// 其中 proc 是一个对象，包含是类似于 MsgProc_XXXXX的一系列函数，分别用来处理不同的消息
	RegMsgProc(proc interface{})
	// 注册消息拥有者
	RegMsgOwner(IMsgOwner)
	// //注册出错时的处理函数
	// RegOnPanicFunc(f func(err error))

	//获取有消息时的chan
	GetCallChan() chan bool
	// SetMainHander 设置父级消息路由器
	SetMainHander(msghandler IMsgHandler)
	// //调用出错处理函数
	// OnPanicFunc(err error)

	getMsgList() *safecontainer.SafeListT[*msgFireInfo]
	getRpcList() *safecontainer.SafeListT[*rpcFireInfo]
	getSrvList() *safecontainer.SafeListT[*srvFireInfo]
	fireMsg(msg *msgFireInfo)
	fireRPC(msg *rpcFireInfo)
	fireSrv(msg *srvFireInfo)
}

// NewMsgHandler 创建一个新的消息处理器
func NewMsgHandler() *MsgHandler {

	return &MsgHandler{

		// enable: true,
		//msgCount:     make(map[string][]int64),
		msgFireInfo:  safecontainer.NewSafeListT[*msgFireInfo](),
		rpcFireInfo:  safecontainer.NewSafeListT[*rpcFireInfo](),
		srvFireInfo:  safecontainer.NewSafeListT[*srvFireInfo](),
		defaultFuncs: make([]reflect.Value, 0, 10),
		msgChan:      make(chan bool, 1),
	}
}

// msgFireInfo 触发一个事件时必须的信息
type msgFireInfo struct {
	handler *MsgHandler
	name    string
	content msgdef.IMsg
}

func (msg *msgFireInfo) GetHandler() *MsgHandler {
	return msg.handler
}

type rpcFireInfo struct {
	handler    *MsgHandler
	methodName string
	content    msgdef.IMsg
}

func (rpc *rpcFireInfo) GetHandler() *MsgHandler {
	return rpc.handler
}

type srvFireInfo struct {
	handler    *MsgHandler
	methodName string
	req, msg   msgdef.IMsg // req路由消息，msg具体消息
}

func (this *srvFireInfo) GetHandler() *MsgHandler {
	return this.handler
}

// MsgHandler 消息处理中心
type MsgHandler struct {
	msgFuncs sync.Map //MsgProc_前缀 的所有方法
	rpcFuncs sync.Map //RPC_前缀     的所有方法
	srvFuncs sync.Map //Srv_前缀     的服务器之间的调用需要回复

	// enable       bool
	defaultFuncs []reflect.Value

	msgFireInfo *safecontainer.SafeListT[*msgFireInfo] //MsgProc_ 消息
	rpcFireInfo *safecontainer.SafeListT[*rpcFireInfo] //RPC_ 消息
	srvFireInfo *safecontainer.SafeListT[*srvFireInfo] //RPC_ 消息
	// onPanicFunc func(err error)
	MsgOwner IMsgOwner //消息拥有者

	msgChan chan bool
	/*
		parent 如果多个msghandlers 共用一个协程的时候，会有一个主MsgHandlers
		这样的话，就可以把所有消息放到这个主MsgHandlers里
	*/
	mainHander IMsgHandler
}

// 获取子处理器
func (this *MsgHandler) GetNewSubHandler() (result *MsgHandler) {
	result = NewMsgHandler()
	result.SetMainHander(this)
	return result
}

// 注册消息拥有者
func (handlers *MsgHandler) RegMsgOwner(owner IMsgOwner) {
	handlers.MsgOwner = owner
}

func (handlers *MsgHandler) getMsgList() *safecontainer.SafeListT[*msgFireInfo] {
	return handlers.msgFireInfo
}
func (handlers *MsgHandler) getRpcList() *safecontainer.SafeListT[*rpcFireInfo] {
	return handlers.rpcFireInfo
}

func (handlers *MsgHandler) getSrvList() *safecontainer.SafeListT[*srvFireInfo] {
	return handlers.srvFireInfo
}

// RegMsg
// RegMsgProc 注册消息处理对象
// 其中 proc 是一个对象，包含是类似于 MsgProc_XXXXX的一系列函数，分别用来处理不同的消息
func (handlers *MsgHandler) RegMsgProc(proc interface{}) {

	v := reflect.ValueOf(proc)
	t := reflect.TypeOf(proc)

	for i := 0; i < t.NumMethod(); i++ {
		methodName := t.Method(i).Name

		ifWarnAnonymousFunc := func() {
			if !logger.CheckKey(logger.LogKey_RegMsgProc) {
				return
			}
			// 获取方法的接收器类型
			recvType := t.Method(i).Type.In(0)
			// 检查接收器类型是否与Outer相同
			// TODO: 目前不太容易判断 当前方法 是否是匿名结构体里面的方法, 只能通过 方法名称对比是否在匿名结构体里面的方法 来判断,折磨.
			if recvType != t {
				logger.Error("注册MsgProc 使用匿名组合是很危险的,请自行判断 ", recvType.String(), t.String())
			}
			logger.Debug(logger.LogKey_RegMsgProc, methodName, ":", t.Method(i).Type.NumIn(), t.Method(i).Type.Name(),
				" 注册MsgProc的方法的接收第一个参数是 ", recvType.String(), " , 本结构体为:", t.String(),
			) //" Method.PkgPath=(", t.Method(i).PkgPath, ",", t.Method(i).Type.String(), ")", v.Method(i).String())
		}
		//MsgProc前缀的所有方法
		msgName, msgHandler, err := handlers.getMsgHandler(methodName, v.MethodByName(methodName))
		if err == nil {
			ifWarnAnonymousFunc()
			handlers.addMsgHandler(msgName, msgHandler)
			continue
		}

		// 判断是否是RPC处理函数
		msgName, msgHandler, err = handlers.getRPCHandler(methodName, v.MethodByName(methodName))
		if err == nil {
			ifWarnAnonymousFunc()
			handlers.addRPCHandler(msgName, msgHandler)
			continue
		}
		// 判断是否是Srv处理函数
		msgName, msgHandler, err = handlers.getSrvHandler(methodName, v.MethodByName(methodName))
		if err == nil {
			ifWarnAnonymousFunc()
			handlers.addSrvHandler(msgName, msgHandler)
			continue
		}
	}

	handlers.addDefaultFunc(proc)
}

func (handlers *MsgHandler) addDefaultFunc(proc interface{}) {

	v := reflect.ValueOf(proc)
	var defaultFunc = v.MethodByName("MsgProc_DefaultMsgHandler")
	if defaultFunc.IsValid() {
		handlers.defaultFuncs = append(handlers.defaultFuncs, defaultFunc)
	}
}

// SetMainHander 设置父级消息路由器
func (handlers *MsgHandler) SetMainHander(msghandler IMsgHandler) {
	if msghandler != nil {
		handlers.mainHander = msghandler
		handlers.msgChan = msghandler.GetCallChan()
	}
}

// 获取有消息的信号量
func (handlers *MsgHandler) GetCallChan() chan bool {
	return handlers.msgChan
}

// FireMsg 触发消息, 保证不被挂起
func (handlers *MsgHandler) FireMsg(name string, content msgdef.IMsg) {
	msg := &msgFireInfo{
		handler: handlers,
		name:    name,
		content: content,
	}
	handlers.fireMsg(msg)
	select {
	case handlers.msgChan <- true:
	default:
	}
}

// 这里会牵扯到级联判断的问题，这样修改可以支持
func (handlers *MsgHandler) fireMsg(msg *msgFireInfo) {
	if handlers.mainHander != nil {
		handlers.mainHander.fireMsg(msg)
	} else {
		handlers.msgFireInfo.Put(msg)
	}
}

// FireRPC 触发消息, 保证不被挂起
func (handlers *MsgHandler) FireRPC(method string, content msgdef.IMsg) {
	msg := &rpcFireInfo{
		handler:    handlers,
		methodName: method,
		content:    content,
	}
	handlers.fireRPC(msg)
	select {
	case handlers.msgChan <- true:
	default:
	}
}

// 这里会牵扯到级联判断的问题，这样修改可以支持
func (handlers *MsgHandler) fireRPC(msg *rpcFireInfo) {
	if handlers.mainHander != nil {
		handlers.mainHander.fireRPC(msg)
	} else {
		handlers.rpcFireInfo.Put(msg)
	}
}

// FireSrv 触发Srv_前缀的函数,保证不被挂起
func (this *MsgHandler) FireSrv(name string, req, msg msgdef.IMsg) {
	srvmsg := &srvFireInfo{
		handler:    this,
		methodName: name,
		req:        req,
		msg:        msg,
	}
	this.fireSrv(srvmsg)
	// if handlers.mainHander != nil {
	// 	handlers.mainHander.msgFireInfo.Put(msg)
	// } else {
	// 	handlers.msgFireInfo.Put(msg)
	// }
	select {
	case this.msgChan <- true:
	default:
	}
}

// 这里会牵扯到级联判断的问题，这样修改可以支持
func (handlers *MsgHandler) fireSrv(msg *srvFireInfo) {
	if handlers.mainHander != nil {
		handlers.mainHander.fireSrv(msg)
	} else {
		handlers.srvFireInfo.Put(msg)
	}
}

// DoMsg 将缓冲的消息一次性处理
func (handlers *MsgHandler) DoMsg() {

	var procName string
	var info interface{}
	var err error
	var msgh *MsgHandler
	defer func() {
		if handlers.getRecover() {
			if err := recover(); err != nil {
				logger.Error(err, procName)
				buf := common.StackTrace()
				common.OnRecover(err, buf, info)
				if msgh != nil && msgh.MsgOwner != nil {
					msgh.MsgOwner.OnPanic(common.GetError(err))
				}
			}
		}
	}()

	for {
		info, err = handlers.msgFireInfo.Pop()
		if err != nil {
			break
		}
		msginfo := info.(*msgFireInfo)
		procName = msginfo.name
		msgh = msginfo.GetHandler()
		e := msginfo.handler.DoNormalMsg(msginfo.name, msginfo.content)
		if e != nil {
			logger.Error(e)
		}
	}

	for {
		info, err = handlers.rpcFireInfo.Pop()
		if err != nil {
			break
		}
		rpcinfo := info.(*rpcFireInfo)
		procName = rpcinfo.methodName
		msgh = rpcinfo.GetHandler()
		e := rpcinfo.handler.DoRPCMsg(rpcinfo.methodName, rpcinfo.content)
		if e != nil {
			logger.Error(e)
		}
	}

	for {
		info, err = handlers.rpcFireInfo.Pop()
		if err != nil {
			break
		}
		msginfo := info.(*srvFireInfo)
		procName = msginfo.methodName
		msgh = msginfo.GetHandler()
		msginfo.handler.DoSrvMsg(msginfo.methodName, msginfo.req, msginfo.msg)

	}
}

// DoNormalMsg 立即触发消息
func (handlers *MsgHandler) DoNormalMsg(name string, content msgdef.IMsg) error {
	if handlers.MsgOwner != nil {
		handlers.MsgOwner.OnMsgBefore(name, content)
		defer handlers.MsgOwner.OnMsged(name, content)
	}

	ifuncs, ok := handlers.msgFuncs.Load(name)
	if !ok {
		if len(handlers.defaultFuncs) == 0 {
			//如果是心跳，没有处理就没有处理，不做error输出
			if name == "HeartBeat" {
				return nil
			}
			return fmt.Errorf("Cant find handler %s", name)
		}

		for _, f := range handlers.defaultFuncs {
			if f.IsValid() {
				f.Call([]reflect.Value{reflect.ValueOf(content)})
			}
		}

		return nil
	}

	for _, msgFunc := range ifuncs.([]reflect.Value) {
		msgFunc.Call([]reflect.Value{reflect.ValueOf(content)})
	}

	return nil
}

// DoRPCMsg RPC执行
func (handlers *MsgHandler) DoRPCMsg(methodName string, content msgdef.IMsg) error {
	if handlers.MsgOwner != nil {
		handlers.MsgOwner.OnRpcBefore(methodName, content)
		defer handlers.MsgOwner.OnRpced(methodName, content)
	}
	ifuncs, ok := handlers.rpcFuncs.Load(methodName)
	if !ok {
		return fmt.Errorf("Method %v can't find", methodName)
	}

	funcs, _ := ifuncs.([]reflect.Value)
	for _, rpcFunc := range funcs {
		outVal := rpcFunc.Call([]reflect.Value{reflect.ValueOf(content)})
		//如果有通用错误处理回调,则处理返回值 传递给通用错误处理
		if handlers.MsgOwner != nil &&
			len(outVal) > 0 && outVal[0].CanInterface() {
			var msg msgdef.IMsg
			if v, ok := content.(msgdef.IMsg); ok {
				msg = v
			}
			if err, ok := outVal[0].Interface().(error); ok && err != nil {
				handlers.MsgOwner.OnRpcReturn(msg, err)
			} else if outVal[0].Interface() == nil {
				handlers.MsgOwner.OnRpcReturn(msg, nil)
			}
		}
	}

	return nil
}

// 调用Srv_前缀的函数
func (this *MsgHandler) DoSrvMsg(name string, req, msg msgdef.IMsg) {
	ifuncs, ok := this.srvFuncs.Load(name)
	if !ok {
		logger.Warnf("DoSrvMsg.Method %s Can't Find", name)
		return
	}
	args := []reflect.Value{reflect.ValueOf(req), reflect.ValueOf(msg)}
	for _, msgFunc := range ifuncs.([]reflect.Value) {
		outVal := msgFunc.Call(args)
		//如果有通用错误处理回调,则处理返回值 传递给通用错误处理
		if this.MsgOwner != nil &&
			len(outVal) > 0 && outVal[0].CanInterface() {
			//process with error
			if err, ok := outVal[0].Interface().(error); ok && err != nil {
				this.MsgOwner.OnSrvReturn(req, msg, err)
			} else if outVal[0].Interface() == nil {
				this.MsgOwner.OnSrvReturn(req, msg, nil)
			}
		}
	}
}

func (handlers *MsgHandler) addMsgHandler(msgName string, msgHandler reflect.Value) {
	ifuncs, ok := handlers.msgFuncs.Load(msgName)

	var funcs []reflect.Value
	if !ok {
		funcs = make([]reflect.Value, 0, 10)
	} else {
		funcs = ifuncs.([]reflect.Value)
	}

	funcs = append(funcs, msgHandler)
	handlers.msgFuncs.Store(msgName, funcs)
}

func (handlers *MsgHandler) addRPCHandler(msgName string, msgHandler reflect.Value) {
	ifuncs, ok := handlers.rpcFuncs.Load(msgName)

	var funcs []reflect.Value
	if !ok {
		funcs = make([]reflect.Value, 0, 10)
	} else {
		funcs = ifuncs.([]reflect.Value)
	}

	funcs = append(funcs, msgHandler)
	handlers.rpcFuncs.Store(msgName, funcs)
}

// 返回true表示有重复的
func (handlers *MsgHandler) addSrvHandler(msgName string, msgHandler reflect.Value) {
	ifuncs, ok := handlers.srvFuncs.Load(msgName)

	var funcs []reflect.Value
	if !ok {
		funcs = make([]reflect.Value, 0, 10)
	} else {
		funcs = ifuncs.([]reflect.Value)
		for _, v := range funcs {
			if logger.CheckKey(logger.LogKey_RegMsgProc) &&
				v.Type().String() == msgHandler.Type().String() {
				logger.Warn("重复注册的消息(可能是正确的):", msgName, " ", msgHandler.Type().String(), " ", v.Type().String())
			}
		}
	}

	funcs = append(funcs, msgHandler)
	handlers.srvFuncs.Store(msgName, funcs)
}

func (handlers *MsgHandler) getMsgHandler(methodName string, v reflect.Value) (string, reflect.Value, error) {
	methodHead := "MsgProc_"
	methodHeadLen := len(methodHead)

	if len(methodName) < methodHeadLen+1 {
		return "", reflect.ValueOf(nil), fmt.Errorf("")
	}

	if methodName[0:methodHeadLen] != methodHead {
		return "", reflect.ValueOf(nil), fmt.Errorf("")
	}

	msgName := methodName[methodHeadLen:]

	//此处应该检查该函数是否是MsgHanderFunc类型的参数
	return msgName, v, nil
}

func (handlers *MsgHandler) getRPCHandler(methodName string, v reflect.Value) (string, reflect.Value, error) {
	if strings.Contains(methodName, "RPC_") {
		return methodName[4:], v, nil
	}

	return "", reflect.ValueOf(nil), fmt.Errorf("")
}

// 获取服务器接口
func (handlers *MsgHandler) getSrvHandler(methodName string, v reflect.Value) (string, reflect.Value, error) {
	if strings.HasPrefix(methodName, "Srv_") {
		return methodName[4:], v, nil
	}

	return "", reflect.ValueOf(nil), fmt.Errorf("")
}

func (handlers *MsgHandler) getRecover() bool {
	if global.GetSrvInst() == nil {
		return viper.GetBool("Config.Revover")
	}
	return global.GetCfgInst().GetRecover()
}
